package org.example.hotel.service;

import org.example.hotel.dto.ReportDTO;
import org.example.hotel.entity.Room;
import org.example.hotel.entity.UsageRecord;
import org.example.hotel.repository.RoomRepository;
import org.example.hotel.repository.UsageRecordRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class ReportService {

    private static final double ROOM_COST_PER_DAY = 200;

    @Autowired
    private RoomRepository roomRepository;

    @Autowired
    private UsageRecordRepository usageRecordRepository;

    public ReportDTO generateReport(LocalDate start, LocalDate end, Integer roomId) {
        ReportDTO report = new ReportDTO();
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter hourFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");

        report.setStartDate(start.format(dateFormatter));
        report.setEndDate(end.format(dateFormatter));
        report.setRoomId(roomId);

        List<Room> rooms;
        if (roomId == null) {
            rooms = roomRepository.findAll();
        } else {
            rooms = Collections.singletonList(roomRepository.findById(roomId).orElseThrow());
        }

        Map<String, Double> stayCostTrend = new TreeMap<>();
        Map<String, Double> acCostTrend = new TreeMap<>();

        Map<String, Integer> fanSpeedDuration = new HashMap<>();
        fanSpeedDuration.put("LOW", 0);
        fanSpeedDuration.put("MEDIUM", 0);
        fanSpeedDuration.put("HIGH", 0);

        // 1. 住房费用统计，判断入住时间是否为空
        for (Room room : rooms) {
            if (room.getCheckInTime() == null) {
                continue; // 跳过无入住时间房间
            }

            LocalDate checkIn = room.getCheckInTime().toLocalDate();
            LocalDate checkOut = (room.getCheckOutTime() != null) ? room.getCheckOutTime().toLocalDate() : LocalDate.now();

            LocalDate iterDate = checkIn.isBefore(start) ? start : checkIn;
            LocalDate endDate = checkOut.isAfter(end) ? end : checkOut;

            while (!iterDate.isAfter(endDate)) {
                String dateStr = iterDate.format(dateFormatter);
                stayCostTrend.put(dateStr, stayCostTrend.getOrDefault(dateStr, 0.0) + ROOM_COST_PER_DAY);
                iterDate = iterDate.plusDays(1);
            }
        }

        // 2. 空调使用记录统计，按小时统计费用
        List<UsageRecord> records;
        if (roomId == null) {
            records = usageRecordRepository.findAll();  // 全部房间的空调记录
        } else {
            records = usageRecordRepository.findByRoomId(roomId);  // 指定房间空调记录
        }

        for (UsageRecord r : records) {
            if (r.getStartTime() == null) {
                continue; // 跳过无开始时间记录
            }

            LocalDateTime usageDateTime = r.getStartTime();

            // 判断使用时间是否在日期范围内（只看日期部分）
            LocalDate usageDate = usageDateTime.toLocalDate();
            if (!usageDate.isBefore(start) && !usageDate.isAfter(end)) {
                String hourStr = usageDateTime.format(hourFormatter);  // 按小时统计

                acCostTrend.put(hourStr, acCostTrend.getOrDefault(hourStr, 0.0) + r.getCost());

                String fanSpeed = r.getFanSpeed();
                long duration = r.getDuration();
                if (fanSpeed != null && fanSpeedDuration.containsKey(fanSpeed)) {
                    fanSpeedDuration.put(fanSpeed, (int) (fanSpeedDuration.get(fanSpeed) + duration));
                }
            }
        }

        // 设置结果
        report.setStayCostTrend(stayCostTrend);
        report.setAcCostTrend(acCostTrend);

        double totalStayCost = stayCostTrend.values().stream().mapToDouble(Double::doubleValue).sum();
        double totalAcCost = acCostTrend.values().stream().mapToDouble(Double::doubleValue).sum();

        Map<String, Double> costRatio = new HashMap<>();
        costRatio.put("StayCost", totalStayCost);
        costRatio.put("ACCost", totalAcCost);
        report.setCostRatio(costRatio);

        int totalDuration = fanSpeedDuration.values().stream().mapToInt(Integer::intValue).sum();
        Map<String, Double> fanSpeedRatio = new HashMap<>();
        if (totalDuration > 0) {
            fanSpeedDuration.forEach((speed, dur) -> fanSpeedRatio.put(speed, dur * 100.0 / totalDuration));
        } else {
            fanSpeedRatio.put("LOW", 0.0);
            fanSpeedRatio.put("MEDIUM", 0.0);
            fanSpeedRatio.put("HIGH", 0.0);
        }
        report.setFanSpeedRatio(fanSpeedRatio);

        return report;
    }

}
